/*
 * Copyright 2009-2010 the original author or authors.
 *
 * Licensed under the Apache license, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.internna.iwebjtracker.sonar.services;

import java.net.URL;
import java.util.Set;
import java.net.MalformedURLException;
import org.dom4j.Node;
import org.dom4j.Document;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.internna.iwebmvc.utils.CollectionUtils;
import org.internna.iwebjtracker.sonar.model.SonarMetrics;
import org.internna.iwebjtracker.sonar.model.SonarConfiguration;

import static org.internna.iwebjtracker.utils.UrlUtils.readUrl;

/**
 * Default implementation to access Sonar and manage data.
 *
 * @author Jose Noheda
 * @since 1.0
 */
public final class SonarManagerImpl implements SonarManager {

    private static final Log logger = LogFactory.getLog(SonarManagerImpl.class);

    /**
     * Access the server and parse the response.
     *
     * @param configuration any
     * @param metrics any
     * @return any
     */
    @Override public SonarMetrics getMetricData(SonarConfiguration configuration, Set<METRICS> metrics) {
        SonarMetrics sonarMetrics = null;
        if (configuration != null) {
            try {
                URL url = buildSonarURL(configuration, metrics);
                sonarMetrics = buildMetrics(readUrl(url));
            } catch (Exception ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Error getting Sonar metrics: " + ex.getMessage());
                }
            }
        }
        return sonarMetrics;
    }

    /**
     * Constructs a valid URL for the Web Service API given a Sonar server instance.
     *
     * @param configuration a non null instance
     * @param metrics any
     * @return a non null URL
     */
    protected URL buildSonarURL(SonarConfiguration configuration, Set<METRICS> metrics) throws MalformedURLException {
        StringBuilder url = new StringBuilder(configuration.getConnectionDetails().getUrl());
        if (url.charAt(url.length() - 1) != '/') {
            url.append('/');
        }
        url.append("api/resources?format=xml&resource=").append(configuration.getResource()).append("&depth=0");
        if (CollectionUtils.isNotEmpty(metrics)) {
            url.append("&metrics=");
            for (METRICS metric : metrics) {
                url.append(metric).append(",");
            }
            if (url.charAt(url.length() - 1) == ',') {
                url = url.deleteCharAt(url.length() - 1);
            }
        }
        return new URL(url.toString());
    }

    /**
     * Parses the XML document retrieving all the metrics from it.
     *
     * @param document any
     * @return any
     */
    protected SonarMetrics buildMetrics(Document document) {
        SonarMetrics metrics = null;
        if (document != null) {
            metrics = new SonarMetrics();
            for (Object node : document.selectNodes("/resources/resource/msr")) {
                Node element = (Node) node;
                METRICS metric = METRICS.fromMetric(element.valueOf("key"));
                SonarMetrics.SonarMetric retrieved = SonarMetrics.createMetric(metric);
                retrieved.setFormatting(element.valueOf("frmt_val"));
                retrieved.setValue(Double.parseDouble(element.valueOf("val")));
                metrics.addMetric(retrieved);
            }
        }
        return metrics;
    }

}
